/* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/


/*************************************************************************
 * File: ovmgr.h
 *************************************************************************
 *\author: starlove
 *************************************************************************/

#ifdef __MLSE_PLATFORM_WIN__

#ifndef __MLSE_NETWORK_OVMGR_H__
#define __MLSE_NETWORK_OVMGR_H__

template <typename T>
class COverlappedList
{
public:

    COverlappedList()
    {
        m_pFree		= NULL;
        m_pFreeLast	= NULL;
    };

    ~COverlappedList()
    {
    };

    void Push( T *ptr )
    {
        if(!ptr) return;
        if ( m_pFree && m_pFreeLast )
        {
            T *p = m_pFreeLast;
            ((LPXOVERLAPPED)m_pFreeLast)->next = ptr;
            m_pFreeLast = ptr;
        }
        else
        {
            m_pFree = ptr;
            m_pFreeLast = ptr;
        }

        m_nSize ++;
    };

    T *Get()
    {
        if (m_pFree != NULL)
        {
            T *p = m_pFree;
            m_pFree = (T *)((LPXOVERLAPPED)m_pFree)->next;
            if (m_pFree == NULL)
            {
                m_pFreeLast = NULL;
            }
            InterlockedIncrement(&m_nInuseSize);
            return p;
        }
        return NULL;
    }

    void Release( T *pPap )
    {
        if (pPap != NULL)
        {
            InterlockedDecrement(&m_nInuseSize);

            if (!m_pFreeLast || !m_pFree)
            {
                m_pFree = pPap;
                m_pFreeLast = pPap;
                return;
            }

            ((LPXOVERLAPPED)m_pFreeLast)->next = pPap;
            ((LPXOVERLAPPED)pPap)->next = NULL;
        }
    }

    void Free( T *pPap )
    {
        if (pPap != NULL)
            free(pPap);
    }

    size_t size()
    {
        return m_nSize;
    }

    size_t freesize()
    {
        return (size_t)m_nSize - m_nInuseSize;
    }

protected:
private:

    T *m_pFree;
    T *m_pFreeLast;

    volatile LONG	m_nInuseSize;
    size_t			m_nSize;
};

#endif
#endif
